﻿using System;
using System.Collections;
using System.Collections.Generic;
using MiniJSON;
using ServiceStack.Redis;

namespace Cache.Redis
{
    public class RedisHelper
    {
        private static RedisHelper sInstance;
        public static RedisHelper instance
        {
            get
            {
                if (sInstance == null)
                {
                    sInstance = new RedisHelper();
                }
                return sInstance;
            }
        }

        private RedisConnect mRedisConnect;

        public RedisHelper()
        {
            mRedisConnect = new RedisConnect();
        }

        // is data exist
        public bool IsHashContainsEntry(string hashId, string key)
        {
            bool result;
            using (IRedisClient writeClient = mRedisConnect.GetWriteClient())
            {
                result = writeClient.HashContainsEntry(hashId, key);
            }
            return result;
        }


        // save object data
        public bool SaveHashObjectData<T>(T t) where T : Model.Public.BaseEntity, new()
        {
            return SaveHashObjectData<T>(t.GetKey(), t);
        }

        // save object data by key
        public bool SaveHashObjectData<T>(string key, T t) where T : Model.Public.BaseEntity, new()
        {
            string hashId = t.GetDBName();
            string value = Json.Serialize(t.ModelChangeToDic());
            bool result = mRedisConnect.SetEntryInHash(hashId, key, value);
            return result;
        }

        // get object data by key
        public T GetObjectDataByKey<T>(string key) where T : Model.Public.BaseEntity, new()
        {
            T t = new T();
            string json_txt = mRedisConnect.GetHash(t.GetDBName(), key);
            if (!string.IsNullOrEmpty(json_txt))
            {
                Dictionary<string, object> json_obj = Json.Deserialize(json_txt) as Dictionary<string, object>;
                t.DicChangeToModel(json_obj);
            }
            return t;
        }

        // get all data list by key
        public List<T> GetAllListByListId<T>(string listId) where T : Model.Public.BaseEntity, new()
        {
            List<T> list = new List<T>();
            List<string> list_str = mRedisConnect.GetAllItemsFromList(listId);
            foreach (var item in list_str)
            {
                T t = new T();
                Dictionary<string, object> json_obj = Json.Deserialize(item) as Dictionary<string, object>;
                t.DicChangeToModel(json_obj);

                list.Add(t);
            }
            return list;
        }

        /// 获取单个hash值
        /// <summary>
        /// 获取单个hash值
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetHash(string hashId, string key)
        {
            return mRedisConnect.GetHash(hashId, key);
        }

        /// 插入hash值
        /// <summary>
        /// 插入hash值
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <param name="value"></param>
        /// <returns></returns>
        public bool SetEntryInHash(string hashId, string key, string value)
        {
            return mRedisConnect.SetEntryInHash(hashId, key, value);
        }

        /// 获取所有hash值
        /// <summary>
        /// 获取所有hash值
        /// </summary>
        /// <param name="hashId"></param>
        /// <returns></returns>
        public Dictionary<string, string> GetAllEntriesFromHash(string hashId)
        {
            return mRedisConnect.GetAllEntriesFromHash(hashId);
        }

        /// 获取单个hash值
        /// <summary>
        /// 获取单个hash值
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public string GetEntriesFromHash(string hashId, string key)
        {
            return mRedisConnect.GetEntriesFromHash(hashId, key);
        }

        /// 获取hash表中多个key的值
        /// <summary>
        /// 获取hash表中多个key的值
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="keys"></param>
        /// <returns></returns>
        public List<string> GetValuesFromHash(string hashId, string[] keys)
        {
            return mRedisConnect.GetValuesFromHash(hashId, keys);
        }

        /// 删除key
        /// <summary>
        /// 删除key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool Remove(string key)
        {
            return mRedisConnect.Remove(key);
        }

        /// 批次插入hash值
        /// <summary>
        /// 批次插入hash值
        /// </summary>
        /// <param name="hashkey"></param>
        /// <param name="values"></param>
        public void SetRangeInHash(string hashkey, List<System.Collections.Generic.KeyValuePair<string, string>> values)
        {
            mRedisConnect.SetRangeInHash(hashkey, values);
        }

        /// 获取hash长度
        /// <summary>
        /// 获取hash长度
        /// </summary>
        /// <param name="hashId"></param>
        /// <returns></returns>
        public int GetHashLength(string hashId)
        {
            return mRedisConnect.GetHashLength(hashId);
        }

        /// SortedSet
        /// <summary>
        /// SortedSet
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public bool AddItemToSortedSet(string setId, string value)
        {
            bool result = mRedisConnect.AddItemToSortedSet(setId, value);
            return result;
        }

        /// SortedSet
        /// <summary>
        /// SortedSet
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="t"></param>
        /// <returns></returns>
        public bool AddItemToSortedSet<T>(T t) where T : Model.Public.BaseEntity, new()
        {
            string setId = t.GetDBName();
            string value = Json.Serialize(t.ModelChangeToDic());
            bool result = mRedisConnect.AddItemToSortedSet(setId, value);
            return result;
        }

        /// 设置过期时间
        /// <summary>
        /// 设置过期时间
        /// </summary>
        /// <param name="key"></param>
        /// <param name="expireAt"></param>
        /// <returns></returns>
        public bool ExpireEntry(string key, DateTime expireAt)
        {
            bool result = mRedisConnect.ExpireEntry(key, expireAt);
            return result;
        }

        /// 设置过期时间
        /// <summary>
        /// 设置过期时间
        /// </summary>
        /// <param name="key"></param>
        /// <param name="expireIn"></param>
        /// <returns></returns>
        public bool ExpireEntry(string key, TimeSpan expireIn)
        {
            bool result = mRedisConnect.ExpireEntry(key, expireIn);
            return result;
        }




        /// 获取hash列表数据
        /// <summary>
        /// 获取hash列表数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public List<T> GetHashObjectList<T>(string hash_id) where T : Model.Public.BaseClass<T>, new()
        {
            List<T> list = new List<T>();
            T t = new T();
            t.SetDBName(hash_id);
            if (!string.IsNullOrEmpty(t.GetDBName()))
            {
                Dictionary<string, string> value = RedisHelper.instance.GetAllEntriesFromHash(t.GetDBName());

                foreach (var item in value.Values)
                {
                    Dictionary<string, object> v = MiniJSON.Json.Deserialize(item) as Dictionary<string, object>;
                    T t1 = new T();
                    t1.DicChangeToModel(v);

                    list.Add(t1);
                }
            }
            return list;
        }

        /// 根据keys获取hash列表数据
        /// <summary>
        /// 根据keys获取hash列表数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hash_id"></param>
        /// <param name="keys"></param>
        /// <returns></returns>
        public List<T> GetHashObjectListByKeys<T>(string hash_id, string[] keys) where T : Model.Public.BaseClass<T>, new()
        {
            T t = new T();
            t.SetDBName(hash_id);
            List<T> list = new List<T>();
            if (!string.IsNullOrEmpty(t.GetDBName()))
            {
                List<string> values = RedisHelper.instance.GetValuesFromHash(t.GetDBName(), keys);
                foreach (var item in values)
                {
                    Dictionary<string, object> v = MiniJSON.Json.Deserialize(item) as Dictionary<string, object>;
                    T t1 = new T();
                    t1.DicChangeToModel(v);

                    list.Add(t1);
                }
            }
            return list;
        }


        /// 根据hashId和key获取hash数据
        /// <summary>
        /// 根据hashId和key获取hash数据
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hash_id"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public T GetHashObject<T>(string hash_id, string key) where T : class, Model.Public.BaseClass<T>, new()
        {
            T t = new T();
            t.SetDBName(hash_id);
            string json_txt = mRedisConnect.GetHash(t.GetDBName(), key);
            if (!string.IsNullOrEmpty(json_txt))
            {
                Dictionary<string, object> json_obj = Json.Deserialize(json_txt) as Dictionary<string, object>;
                t.DicChangeToModel(json_obj);
                return t;
            }
            else
            {
                return null;
            }
        }

        /// 保存hash值
        /// <summary>
        /// 保存hash值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hash_id"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public bool SaveHashObject<T>(T t) where T : Model.Public.BaseClass<T>, new()
        {
            //t.SetDBName(hash_id);
            string hashId = t.GetDBName();
            string key = t.GetKey().ToString();
            string value = Json.Serialize(t.ModelChangeToDic());
            bool result = mRedisConnect.SetEntryInHash(hashId, key, value);
            return result;
        }

        /// 批量插入hash值
        /// <summary>
        /// 批量插入hash值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="t"></param>
        public void SaveRangeObjectInHash<T>(string hash_id, List<T> list) where T : Model.Public.BaseClass<T>, new()
        {
            T t = new T();
            t.SetDBName(hash_id);
            string hashId = t.GetDBName();
            List<KeyValuePair<string, string>> valueList = new List<KeyValuePair<string, string>>();
            foreach (var item in list)
            {
                valueList.Add(new KeyValuePair<string, string>(item.GetKey().ToString(), MiniJSON.Json.Serialize(item.ModelChangeToDic())));
            }
            mRedisConnect.SetRangeInHash(hashId, valueList);
        }

        /// 删除hash列表中的某个值
        /// <summary>
        /// 删除hash列表中的某个值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hash_id"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool RemoveObject<T>(string hash_id, string key) where T : Model.Public.BaseClass<T>, new()
        {
            T t = new T();
            t.SetDBName(hash_id);
            return RemoveObject(t.GetDBName(), key);
        }

        /// 删除hash中的单个数据
        /// <summary>
        /// 删除hash中的单个数据
        /// </summary>
        /// <param name="hashId"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool RemoveObject(string hashId, string key)
        {
            return mRedisConnect.RemoveEntryFromHash(hashId, key);
        }

        /// 删除整个key
        /// <summary>
        /// 删除整个key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool RemoveKey<T>(string key) where T : Model.Public.BaseClass<T>, new()
        {
            T t = new T();
            t.SetDBName(key);
            return mRedisConnect.Remove(t.GetDBName());
        }

        /// 删除整个key
        /// <summary>
        /// 删除整个key
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public bool RemoveKey<T>() where T : Model.Public.BaseClass<T>, new()
        {
            T t = new T();
            return mRedisConnect.Remove(t.GetDBName());
        }

        /// 保存hash值
        /// <summary>
        /// 保存hash值
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="hash_id"></param>
        /// <param name="t"></param>
        /// <returns></returns>
        public bool SaveHashValue<T>(T t, string key) where T : Model.Public.BaseClass<T>, new()
        {
            string hashId = t.GetDBName();
            string value = Json.Serialize(t.ModelChangeToDic());
            bool result = mRedisConnect.SetEntryInHash(hashId, key, value);
            return result;
        }
    }
}
